﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GoodTrader.GTDownload
{
    public class CpOptionDownloader : CpDownLoader
    {
        public CpOptionDownloader(CpDownLoadManager aDownManager, CpOptionData aData)
            : base(aDownManager)
        {
            mData = aData;
            m_OptChartFetcher.Received += new CPSYSDIBLib._ISysDibEvents_ReceivedEventHandler(OnReceived);
        }

        private string mCode = "";
        public string Code
        {
            get { return mCode; }
            set { mCode = value; }
        }
        
        private short mCycle = 1;
        public short Cycle
        {
            get { return mCycle; }
            set { mCycle = value; }
        }

        private long mStartDate = 0;
        public long StartDate
        {
            get { return mStartDate; }
            set { mStartDate = value; }
        }
        private long mEndDate = 0;
        public long EndDate
        {
            get { return mEndDate; }
            set { mEndDate = value; }
        }

        // 요청구분 : 1 - 기간별, 2 - 개수 데이터
        private char mReqType = '2';
        public char ReqType
        {
            get { return mReqType; }
            set { mReqType = value; }
        }
        // 요청 개수
        private uint mReqCount = 10;
        public uint ReqCount
        {
            get { return mReqCount; }
            set { mReqCount = value; }
        }
        // 차트 구분 : 'T' - 틱, 'S' - 초, 'm' - 분, 'M' - 월, 'W' - 주, 'D' - 일
        private char mChartType = 'm';
        public char ChartType
        {
            get { return mChartType; }
            set { mChartType = value; }
        }

        private double[] arrVal = new double[GTGlobal.MaxDownloadCount];

        // 주간 선물 차트 데이터를 가져오는 객체
        private CPSYSDIBLib.FutOptChartClass m_OptChartFetcher = new CPSYSDIBLib.FutOptChartClass();
        private CpOptionData mData = null; // new CpFutureData();
        public CpOptionData Data
        {
            get { return mData; }
            set { mData = value; }
        }

        public void BlockDownload()
        {
            //object code = m_CpFutureCode.GetData(0, 0);
            if (mCode == "")
                return;

            int[] fields = new int[] { 0, 1, 2, 3, 4, 5, 6, 8, 27, 29 };
            m_OptChartFetcher.SetInputValue(0, mCode);
            m_OptChartFetcher.SetInputValue(1, mReqType);
            m_OptChartFetcher.SetInputValue(2, mStartDate);
            m_OptChartFetcher.SetInputValue(3, mEndDate);
            m_OptChartFetcher.SetInputValue(4, GTGlobal.MaxDownloadCount);
            m_OptChartFetcher.SetInputValue(5, fields);
            m_OptChartFetcher.SetInputValue(6, mChartType);
            m_OptChartFetcher.SetInputValue(7, mCycle);

            // 데이터 수신 요청을 한다.
            try
            {
                // 데이터 수신 요청을 한다.
                m_OptChartFetcher.BlockRequest();
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }


            object dataCount = m_OptChartFetcher.GetHeaderValue(3);

            /*
            for (int i = Convert.ToInt32(dataCount) - 1, j = 0; i > -1; i--, j++)
            {
                mData.Date[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(0, i)); // 날짜
                mData.Time[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(1, i)); // 시간
                mData.Open[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(2, i).ToString()); // 시가
                mData.High[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(3, i).ToString()); // 고가
                mData.Low[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(4, i).ToString()); // 저가
                mData.Close[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(5, i).ToString()); // 종가
                mData.Amount[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(7, i).ToString()); // 거래량
            }
             */
            for (int i = 0, j = mData.Time.Length - 1; i < Convert.ToInt32(dataCount); i++, j--)
            {
                mData.Date[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(0, i)); // 날짜
                mData.Time[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(1, i)); // 시간
                double tOpen = Convert.ToDouble(m_OptChartFetcher.GetDataValue(2, i).ToString());
                //if (tOpen == 0.0)
                //    break;
                mData.Open[j] = tOpen; // 시가
                mData.High[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(3, i).ToString()); // 고가
                mData.Low[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(4, i).ToString()); // 저가
                mData.Close[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(5, i).ToString()); // 종가
                mData.Amount[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(7, i).ToString()); // 거래량
            }

            //Console.WriteLine("Block Request option : " + mCode + mOldTime.ToString() + "::" + mEndTime.ToString());

            // 여기서 증권사 시간을 차트 시간으로 변환해 준다.
            GTGlobal.StockTimeToChartDirectorTime(mData.Date, mData.Time, mData.cTime);
        }

        // 다운로드 함수로 상속 클래스의 함수를 재정의 한다.
        public override void Download()
        {
            if (mCode == "")
                return;

            // 이미 다운 받은 상태이므로 먼저 베이스 클래스의 함수를 실행한다.
            base.Download();
            // 여기서 다운로드 할 내용을 실행한다.
            //System.Windows.Forms.MessageBox.Show("FutOptDownStarted");

            int[] fields = new int[] { 0, 1, 2, 3, 4, 5, 6, 8, 27, 29 };
            m_OptChartFetcher.SetInputValue(0, mCode);
            m_OptChartFetcher.SetInputValue(1, mReqType);
            m_OptChartFetcher.SetInputValue(2, mStartDate);
            m_OptChartFetcher.SetInputValue(3, mEndDate);
            m_OptChartFetcher.SetInputValue(4, mReqCount);
            m_OptChartFetcher.SetInputValue(5, fields);
            m_OptChartFetcher.SetInputValue(6, mChartType);
            m_OptChartFetcher.SetInputValue(7, mCycle);

            // 데이터 수신 요청을 한다.
            try
            {
                // 데이터 수신 요청을 한다.
                m_OptChartFetcher.Request();
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        public override void OnReceived()
        {
            // 베이스 클래스의 함수를 먼저 호출한다. 여기서 이벤트가 다시 설정된다. 
            base.OnReceived();

            if (mData == null)
                return;

            object dataCount = m_OptChartFetcher.GetHeaderValue(3);
            if (Convert.ToInt32(dataCount) <= 1)
                return;

            double curDate = Convert.ToDouble(m_OptChartFetcher.GetDataValue(0, 0)); // 날짜
            double curTime = Convert.ToDouble(m_OptChartFetcher.GetDataValue(1, 0)); // 시간
            double curOpen = Convert.ToDouble(m_OptChartFetcher.GetDataValue(2, 0).ToString()); // 시가
            double curHigh = Convert.ToDouble(m_OptChartFetcher.GetDataValue(3, 0).ToString()); // 고가
            double curLow = Convert.ToDouble(m_OptChartFetcher.GetDataValue(4, 0).ToString()); // 저가
            double curClose = Convert.ToDouble(m_OptChartFetcher.GetDataValue(5, 0).ToString()); // 종가
            double curAmount = Convert.ToDouble(m_OptChartFetcher.GetDataValue(7, 0)); // 거래량


            double befDate = Convert.ToDouble(m_OptChartFetcher.GetDataValue(0, 1)); // 날짜
            double befTime = Convert.ToDouble(m_OptChartFetcher.GetDataValue(1, 1)); // 시간
            double befOpen = Convert.ToDouble(m_OptChartFetcher.GetDataValue(2, 1).ToString()); // 시가
            double befHigh = Convert.ToDouble(m_OptChartFetcher.GetDataValue(3, 1).ToString()); // 고가
            double befLow = Convert.ToDouble(m_OptChartFetcher.GetDataValue(4, 1).ToString()); // 저가
            double befClose = Convert.ToDouble(m_OptChartFetcher.GetDataValue(5, 1).ToString()); // 종가
            double befAmount = Convert.ToDouble(m_OptChartFetcher.GetDataValue(7, 1)); // 거래량

            // 마지막 인덱스를 가져온다.
            int endIndex = mData.Time.Length - 1;

            double beforeTime = mData.Time[endIndex - 1];

            //Console.WriteLine("option beforetime ->" + beforeTime.ToString() + "::" + "befTime ->" + befTime.ToString());
            //Console.WriteLine("curOpen" + curOpen.ToString());
            //Console.WriteLine("curClose" + curClose.ToString());
            //Console.WriteLine("curHigh" + curHigh.ToString());
            //Console.WriteLine("curLow" + curLow.ToString());

            if (befTime != beforeTime)
            {
                GTGlobal.ShiftArrayVal(curDate, befDate, mData.Date, arrVal);
                GTGlobal.ShiftArrayVal(curTime, befTime, mData.Time, arrVal);
                GTGlobal.ShiftArrayVal(curOpen, befOpen, mData.Open, arrVal);
                GTGlobal.ShiftArrayVal(curHigh, befHigh, mData.High, arrVal);
                GTGlobal.ShiftArrayVal(curLow, befLow, mData.Low, arrVal);
                GTGlobal.ShiftArrayVal(curClose, befClose, mData.Close, arrVal);
                GTGlobal.ShiftArrayVal(curAmount, befAmount, mData.Amount, arrVal);

                // 증권사 시간을 차트시간으로 변환해 준다.
                double cCurTime = 0.0;
                // 현재 시간을 차트 시간으로 변환한다.
                GTGlobal.StockTimeToChartDirectorTime(curDate, curTime, ref cCurTime);
                // 증권사 시간을 차트시간으로 변환해 준다.
                double cBefTime = 0.0;
                // 현재 시간을 차트 시간으로 변환한다.
                GTGlobal.StockTimeToChartDirectorTime(curDate, curTime, ref cBefTime);
                GTGlobal.ShiftArrayVal(cCurTime, cBefTime, mData.cTime, arrVal);
            }
            else
            {
                mData.Date[endIndex] = curDate;
                mData.Time[endIndex] = curTime;
                // 증권사 시간을 차트시간으로 변환해 준다.
                double cTime = 0.0;
                // 현재 시간을 차트 시간으로 변환한다.
                GTGlobal.StockTimeToChartDirectorTime(curDate, curTime, ref cTime);
                // 차트 시간에 넣어준다.
                mData.cTime[endIndex] = cTime;
                mData.Open[endIndex] = curOpen;
                mData.High[endIndex] = curHigh;
                mData.Low[endIndex] = curLow;
                mData.Close[endIndex] = curClose;
                mData.Amount[endIndex] = curAmount;
            }
        }
    }
}
